[PR]今日のニュースは
「Infoseek モバイル」

知られざる WAVE ファイルの中身

 音楽ファイルのもっとも基本である WAVE ファイル。 音楽データを扱うプログラムを書いたことがある人なら、 一度はその中身について勉強したことがあるでしょう。 しかし、実は WAVE ファイルの中にはあまり世に知られていない、 マニアックなデータが埋め込まれていることもあります。 今回は、その辺を深く掘り下げてみましょう。
  1. Introduction
  2. RIFF 概説
    1. RIFF の詳しいフォーマット
  3. 色々なチャンク
  4. まとめ

Introduction

 今回は WAVE ファイルの中身について触れるわけですが、 実際に入っているデータ部分(PCM)ではなく、 そのおまけでくっついているデータについての解説です。
 WAVE ファイルは RIFF - Resource Interchange File Format というフォーマットで保存されています。 この RIFF という単語も、よく聞く単語です。 こいつの作りは超簡単で、効率よくデータの追加・削除が行える設計になっています。
 次の章では、まずは簡単に RIFF の構造を学んでみましょう。

RIFF 概説

 RIFF での決まりは次の事柄です。
 上から見ていきましょう。まずチャンクです。 というより、RIFF を構成するのがこのチャンクの一言に尽きます。 このチャンクというのは、中に実際のデータが入っている箱のようなものです。 つまり、WAVE ファイルの中にはいくつかの箱が入っており、 その箱を開けると目的のデータが入っているということです。 イメージでいうとこんな感じ。

RIFF の構造

 次の、チャンクの名前、というものです。 ファイルを開けて箱があるものの、どれが何の箱なのか判らないと、データを使いようがありません。 そのため、チャンクには必ず名前がついています。 上の例だと、RIFF, WAVE, fmt , data がそうです。 このように、名前は 32 ビットの、ASCII コードから成り立っています。 これを、FourCC(おそらく Four Character Codes)と呼んでいます。 fmt  にも、正確には t の後ろにスペースが入っています。
 お次。チャンクの中にチャンクを持つことができる、というもの。 これは、箱を開けたらデータではなく、また箱が入っているという感じです。 もっというと、RIFF 自体がチャンクなので、その中に fmt  やら data やらのチャンクが入っている、 ということになります。
 チャンクの境界は 16 ビットです。 1 バイト分余ってしまったら、0x00 を入れて補完しなければいけません。
 さて最後の、そのファイルには必要のないチャンクを入れてもよい、というところですが、 WAVE ファイルには必須チャンクとして fmt  と data があります。 この 2 つは必ず入っていなければなりません。 ですが、その他に余計なチャンクを入れてもかまわない、ということです。 逆に、読み込む側は、そういう意味不明なチャンクが出てきたら、 ちゃんと読み飛ばすようにしなければなりません。

RIFF の詳しいフォーマット

 RIFF の大まかな規約は以上ですが、 それでは煮え切らんという方のために、詳しいフォーマットを書いておきます。

詳細フォーマット

 とある WAVE ファイルの頭の部分です。まず、『RIFF』の文字があります。 これは、『このファイルは RIFF だよ〜』との宣言です。
 次の 4 バイトはそのチャンクサイズです。 チャンクには、そのチャンクがどれだけのサイズを持っているかを示すサイズが必須となります。 あとは、基本的にチャンク名 + チャンクサイズ + 実データの繰り返しで保存されます。
 さて、その次の 8 バイト目からは WAVE チャンクです。  『これは WAVE ファイルだよ〜』と言っているのです。 8 バイト目から始まるチャンクは特別で、サイズ定義を持ちません。
 では次。『fmt 』です。これは、PCM のフォーマットが記録されています。 mmsystem.h にある『WAVEFORMAT』あるいは『WAVEFORMATEX』の形で入っています。 どちらで入っているかは、チャンクサイズを調べれば判ります。
 次の 4 バイトは前述の通り、チャンクサイズ。 言い忘れましたが、 チャンクサイズはチャンク名 4 バイトとサイズ定義 4 バイト分の計 8 バイトは勘定に入っていません。 あくまで実データ部分のサイズということになります。 というわけで、その次の 14h バイト目から 10h はデータ部分となります。
 次に『data』チャンクが出てきました。 ここに PCM データが格納されています。サイズもでかく、1a00918h もあります。
 と、こんな感じです。非常に簡単でいいですね。

色々なチャンク

 さて、ここいらで本題に入りましょう。 WAVE ファイルの様々なデータというのは言うまでもなく、このチャンクの中に入っています。 正確には非公式なチャンクですが、一般的と思われるものをいくつかご紹介いたしましょう。
LIST これは WAVE ファイルに限ったことでなく、他の RIFF ファイルでも共通のことです。 LIST は上で触れた、チャンクの中にチャンクを持つための特別なチャンクです。
cue  キューポイント、まぁなんかのための位置情報とでも言っておきましょうか。 サンプリング位置を指定して文字列を埋め込んだりできます。 肝心の中身ですが、私もよく判っていません。 ただ、キュー ID とサンプリング位置らしき値だけは読み取れるので、 それ以外は無視しています。 私はこのチャンクを使って WAVE ファイルを無限ループさせています。
adtl ファイルの詳しい内容を埋め込めるようです。これもリストチャンクです。
labl 先ほど定義したキューポイントにラベル文字を埋め込めます。 ループの始点と終点を記述するのに便利です。

まとめ

 RIFF は基本なんでも埋め込めるので、 自作プログラムで扱うときは、あったほうがいい情報を埋め込みまくってもいいかもしれませんね。


[戻る]

[トップへ戻る]